/*
 * Copyright 2009 Armando Blancas
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package taskgraph.ports;

import java.io.EOFException;
import java.io.IOException;

/**
 * An input interface to a Channel of object references as elements.
 * 
 * @author Armando Blancas
 * @param <E> The type of elements that go through a channel.
 */
public interface InputPort<E> extends Port {
	
    /**
     * Reads and returns the next element. 
     *
     * @return The element read.
     * @throws EOFException If the channel reaches the end.
     * @throws IOException If an I/O error occurs.
     */
    E read() throws EOFException, IOException;

    /**
     * Reads into an array of elements.
     * 
     * Reads a number of elements from this input pipe and stores them into
     * the element array {@code e}. The number of elements actually 
     * read is returned as an {@code int}. This method blocks until input data
     * is available, end of file is detected, or an exception is thrown.
     *
     * <p>If the length of {@code e} is zero, then no elements are read and
     * {@code 0} is returned; otherwise, there is an attempt to read at
     * least one {@code element}. If no element is available because the output
     * end is closed, an {@code IOException} is thrown; otherwise, at least
     * one element is read and stored into {@code e}.
     *
     * <p>The first element read is stored into element {@code e[0]}, the
     * next one into {@code e[1]}, and so on. The number of elements read is,
     * at most, equal to the length of {@code e}. Let <i>k</i> be the
     * number of elements actually read; these elements will be stored in 
     * elements {@code e[0]} through {@code e[k-1]}, leaving elements 
     * {@code e[k]} through {@code e[e.length-1]} unaffected.
     * 
     * <p>The general contract for {@code read(e)} is that it should have 
     * exactly the same effect as the call {@code read(e, 0, e.length)}.
     *
     * @param e The element array into which the data is read.
     * @return The total number of elements read into the array.
     * @throws IOException If the first element cannot be read, the output end
     *         has been closed, or if some other I/O error occurs.
     * @throws NullPointerException If {@code e} is {@code null}.
     */
    int read(E[] e) throws IOException;

    /**
     * Reads into an array of elements.
     * 
     * Reads up to {@code len} elements from this input pipe into an array of
     * elements. Less than {@code len} elements will be read if the output
     * end of the data pipe is closed or if {@code len} exceeds the pipe's 
     * buffer size. If {@code len} is zero, then no elements are read and 0 is
     * returned; otherwise, the method blocks until at least 1 element of 
     * input is available, the output end is closed, or an exception is thrown.
     *
     * @param e    The element array into which the data is read.
     * @param off  The start offset in the destination array {@code e}.
     * @param len  The maximum number of elements to read.
     * @return     The total number of elements read into the array.
     * @throws NullPointerException If {@code e} is {@code null}.
     * @throws IndexOutOfBoundsException If {@code off} is negative, 
     *         {@code len} is negative, or {@code len} is greater than 
     *         {@code e.length - off}.
     * @throws IOException If the pipe is {@code broken},
     *		   closed, or if an I/O error occurs.
     */
    int read(E[] e, int off, int len) throws IOException;

    /**
     * Discards a number of elements from the buffer.
     * 
     * Makes an attempt to skip over <code>n</code> elements of data from the
     * channel, discarding the skipped ones. However, it may skip over some 
     * smaller number of elements, possibly zero. This may result from any of
     * a number of conditions; reaching end of channel before <code>n</code>
     * elements have been skipped is only one possibility. This method never 
     * throws an <code>EOFException</code>. 
     * The actual number of elements skipped is returned.
     *
     * @param n The number of elements to be skipped.
     * @return The number of elements actually skipped.
     * @throws IOException If an I/O error occurs.
     */
    int skipElements(int n) throws IOException;

}
